package com.denlaku.longan.controller.impl;

import com.denlaku.longan.anno.Audit;
import com.denlaku.longan.anno.VarBy;
import com.denlaku.longan.anno.VarOp;
import com.denlaku.longan.audit.AuditVariables;
import com.denlaku.longan.controller.DataOriginController;
import com.denlaku.longan.http.Resp;
import com.denlaku.longan.http.Return;
import com.denlaku.longan.qo.DataOriginQuery;
import com.denlaku.longan.qo.Query;
import com.denlaku.longan.service.DataOriginService;
import com.denlaku.longan.service.ObjectTagService;
import com.denlaku.longan.service.TenantMemObjPermService;
import com.denlaku.longan.util.Objects;
import com.denlaku.longan.util.RsaUtils;
import com.denlaku.longan.vo.DataOrigin;
import com.denlaku.longan.vo.PageBy;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author tianx
 */
@RestController
public class DataOriginControllerImpl implements DataOriginController {
	@Autowired
	private DataOriginService dataOriginService;

	@Autowired
	private ObjectTagService objPermTagService;

	@Autowired
	private TenantMemObjPermService tenantMemObjPermService;

	@VarOp
	@Override
	@Audit(message = "add data source: {#dataOrigin.name}", operation = "audit.operation.addDataSource", module = "DataSource")
	public Return<Long> add(@RequestBody DataOrigin dataOrigin) {
		decryptPwd(dataOrigin);
		dataOriginService.add(dataOrigin);
		return Resp.success(dataOrigin.getId());
	}

	@VarOp
	@Override
	@Audit(message = "update data source: {#dataOrigin.name}", operation = "audit.operation.updateDataSource", module = "DataSource")
	public Return<Void> update(@RequestBody DataOrigin dataOrigin) {
		decryptPwd(dataOrigin);
		dataOriginService.update(dataOrigin);
		return Resp.success();
	}

	@Override
	@Audit(message = "update data source: {#name}", operation = "audit.operation.deleteDataSource", module = "DataSource")
	public Return<Void> delete(Long id) {
		DataOrigin dataOrigin = dataOriginService.get(Query.of(id));
		String name = Optional.ofNullable(dataOrigin).map(DataOrigin::getName).orElse(String.valueOf(id));
		AuditVariables.set("name", name);
		dataOriginService.delete(Query.of(id));
		return Resp.success();
	}

	@Override
	public Return<Boolean> test(@RequestBody DataOrigin dataOrigin, String flag) {
		decryptPwd(dataOrigin);
		boolean test = dataOriginService.test(dataOrigin, flag);
		return Resp.success(test);
	}

	private void decryptPwd(DataOrigin dataOrigin) {
		String password = dataOrigin.getPassword();
		if (StringUtils.isNotEmpty(password)) {
            dataOrigin.setPassword(RsaUtils.decrypt(password));
		}
	}

	@VarBy
	@Override
	public Return<List<DataOrigin>> pageList(DataOriginQuery query, PageBy pageBy) {
        tenantMemObjPermService.setPermTagIds(query);
        PageHelper.startPage(pageBy.getPage(), pageBy.getSize());
        List<DataOrigin> list = dataOriginService.list(query);
		setTagName(query.getTenantId(), list);
		return Resp.success(list);
	}

	private void setTagName(Long tenantId, List<DataOrigin> list) {
		Set<Long> tagIds = list.stream().map(DataOrigin::getTagId).filter(Objects::nonNull)
			.collect(Collectors.toSet());
		Map<Long, String> tagMap = objPermTagService.getTagNameMap(Query.of(tenantId, tagIds));
		list.forEach(ds -> ds.setTagName(tagMap.get(ds.getTagId())));
	}

	@Override
	public Return<List<DataOrigin>> list(DataOriginQuery query) {
        tenantMemObjPermService.setPermTagIds(query);
		List<DataOrigin> list = dataOriginService.list(query);
		return Resp.success(list);
	}

	@Override
	public Return<DataOrigin> get(@RequestParam("id") Long id) {
		DataOrigin dataOrigin = dataOriginService.get(Query.of(id));
		return Resp.success(dataOrigin);
	}

}
